Cherry-pick of
8156b3989a82f2ddf9504d8248496e9b124be7f3
Use CU2BYTES for byte sizing in two allocation sites (#909)
Two allocation sites multiplied by PCRE2_CODE_UNIT_WIDTH (the bit width:
8, 16, or 32) where the CU2BYTES(x) byte-count helper is intended. The
result over-allocates by the code-unit byte width: 8x in 8-bit mode, 16x
in 16-bit, 32x in 32-bit. Subsequent memcpy calls already use CU2BYTES
correctly, so no out-of-bounds write occurs; the over-allocation is
leaked until the buffer is freed.
Also guard each site against integer overflow in
sizeof(pcre2_memctl) + CU2BYTES(N + 1) by rejecting N greater than
(PCRE2_SIZE_MAX - sizeof(pcre2_memctl)) / CU2BYTES(1) - 1.
(cherry picked from commit
31ec59526d641b85108c726fe201effc5dca8627)
/* Allocate memory for the buffer, with hidden space for an allocator at
the start. The next time round the loop runs the conversion for real. */
- allocated = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
- (*bufflenptr + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)ccontext);
- if (allocated == NULL) return PCRE2_ERROR_NOMEMORY;
+ if (*bufflenptr > ((PCRE2_SIZE_MAX - sizeof(pcre2_memctl)) /
+ CU2BYTES(1)) - 1 ||
+ (allocated = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
+ CU2BYTES(*bufflenptr + 1),
+ (pcre2_memctl *)ccontext)) == NULL)
+ return PCRE2_ERROR_NOMEMORY;
*buffptr = (PCRE2_UCHAR *)(((char *)allocated) + sizeof(pcre2_memctl));
use_buffer = *buffptr;
PCRE2_UCHAR *yield;
rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
if (rc < 0) return rc;
-yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
- (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
-if (yield == NULL) return PCRE2_ERROR_NOMEMORY;
+if (size > ((PCRE2_SIZE_MAX - sizeof(pcre2_memctl)) / CU2BYTES(1)) - 1 ||
+ (yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
+ CU2BYTES(size + 1), (pcre2_memctl *)match_data)) == NULL)
+ return PCRE2_ERROR_NOMEMORY;
yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));
memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],
CU2BYTES(size));